# -*- coding: utf-8 -*-
import sys
from sintax import sintax
from tipo import STRING, typeofstring
#
# 	ANALISADOR LEXICO
#
class token:
	def __init__(self, tkstr, linha=-1):
		self.tipo = "nenhumtipo"
		self.tok = tkstr
		self.col = -1
		self.lin = linha
	def __str__(self):
		return "<token " + str(typeofstring(self.tipo)) +  " -> '" + self.tok + "' L:" + str(self.lin) +" C:" + str(self.col) + " >"
		
	def gettoken(self):
		return self.tok
	def gettipo(self):
		return self.tipo

class scanner:
	def __init__(self, nameoffile=""):
		self.line=""
		self.versao = "P0.940"
		self.sintax = sintax()
		self.expr = [' ', '..', ',','(',')', '[', ']', '++', '+','-', '*', '/', ':=', '=', ':',';', ]
		self.blocos = (['\\','\n', None],  ['(*', '*)', None], ['\"', '\"', STRING])
		self.buffer_line = []
		self.prox_char = None # proximo caracter
		self.end_token = False # indica o final dos tokens no arquivo
		self.end_file = False # indica o final do arquivo 
		self.nextline = None
		self.linhanoarquivo = 0 
		self.nmfile = nameoffile
		if not (nameoffile == ""):
			self.f = open(self.nmfile, "r")
	
	def setfile(self, nameoffile):
		self.nmfile = nameoffile
		self.f = open(self.nmfile, "r")
		
	def bloco(self, line):
		fid1 = ""
		fid2 = ""
		line_original = line
		linefull = line
		tipo = 0
		encontrou = False
		for a in self.blocos:
			if line.find(a[0])<>-1:
				tipo=a[2]
				fid1=a[0]
				fid2=a[1]
				if line.find(a[0]) < 1:
					#print "ENCONTROU->"+a[0]
					encontrou=True
					#print fid2 + "->" + fid1
					#print line
					line = line[line.find(a[0])+1:]
					#print line
					while not line.find(fid2)<>-1:
						line = self.readlineinfile()
						linefull+=line
						if self.end_file:
							sys.exit(1)
				else:
					# Separa o que vem antes e manda seguir 
					# deixa o bloco pronto para ser lido
					#
					self.nextline = line[line.find(fid1):]
					return line[:line.find(fid1)] + " "
			
				#print line
		if encontrou:
			# Se encontrou um comentario ou um bloco ex: string
			linefull=linefull[linefull.find(fid1)+len(fid1):]
			linefull=linefull[:linefull.find(fid2)]
			#print "linefull -> " + str(linefull)
			if (not ((tipo==None) or (fid1+linefull+fid2==None))) :
                                #print fid1+linefull+fid2
				t = token(fid1+linefull+fid2)
				#print "add"	
				self.sintax.settypeintoken(t)
				self.buffer_line.append(t)
			result = line[line.find(fid2)+len(fid2):]
			#print "RESULT" + str(result)
			return result
		else:
			return line_original
	
	def readlineinfile(self):
		if (self.nextline==None):
			self.linhanoarquivo+=1
			linha = self.f.readline()
		else:
			#print "NEXT LINE ATIVADO"
			
			linha = self.nextline
			#print linha
			self.nextline = None
			
		# É o final do arquivo
		if len(linha) <> 0:
			# troca todas as novas linhas por espaço em branco
			
			return linha
		else:
			self.end_file=True
			return None
			
	def getnexttoken(self, readonly=False):
		# Se o tem tokens no buffer retornar eles
		#print "============ BUFFER ============="
                for i in self.buffer_line: 
                        #print i
			pass
                #print "================================="
		if len(self.buffer_line)>1:
                        if readonly:
				return self.buffer_line[len(self.buffer_line)-1]
			else:
				return self.buffer_line.pop()
		else:
                        line = self.readlineinfile()
                        #print "LINE",line
                        #if line==None:
                                #print "NONE MEU DEUS"
			self.fragtoken(line)
			
			#print "BUFFERLINE", str(self.buffer_line)
			# limpa a fila
			for i in self.buffer_line:
				if i == None:
					i.pop()
			self.buffer_line.reverse()
			if len(self.buffer_line)>0:
		                if readonly:
					return self.buffer_line[len(self.buffer_line)-1]
				else:
					return self.buffer_line.pop()
				
			
	def fragtoken(self, line):
                #for i in range(((len(line)-1))):
                #        print line[i]
                #print "LINE ->\"" +str(line).replace(str(chr(10)), "")+"\""
		if  not (line == None) and not (str(line).replace(str(chr(10)),"").strip())=="":
			#print "LINE", line
			line = line.replace("\n"," ").replace("\r","").replace("\t"," ").replace(str(chr(13))+str(chr(10))," ")
			# verifica o inicio de um bloco
			line = self.bloco(line)
			line = line.replace("\n"," ").replace("\r","").replace("\t"," ").replace(str(chr(13))+str(chr(10))," ")
			#dicionario com informacoes do local e tamanho
			findexpr = {}
			index = 0 
			while index<len(line):
				if line[index:index+2] in self.expr:
					findexpr[index] = 2
					index+=2
				elif line[index] in self.expr:
					findexpr[index] = 1
					index+=1
				else:
					index+=1
			keys = findexpr.keys()
			keys.sort()
			ant = None
			for i in keys:
				if ant<>None:
					indexant = ant+findexpr[ant]
				else:
					indexant = 0
				pala = line[indexant:i]
				ex = line[i:i+findexpr[i]]
				ant = i
				pala = pala.replace(" ", "")
                                
				if pala<>'':
					t = token(pala, self.linhanoarquivo)
					self.sintax.settypeintoken(t)
					self.buffer_line.append(t)
				ex = ex.replace(" ", "")
				if ex<>'':
					t = token(ex, self.linhanoarquivo)
					self.sintax.settypeintoken(t)
					#print t
					self.buffer_line.append(t)
		else:
			#print "CAI NO ELSEX"
			self.nextline==None
			if not self.end_file:
                        	line = self.readlineinfile()
				return self.fragtoken(line)
		
	def testeallfile(self):
		list = []
		while not self.end_file:
			print "tk:" + str(self.getnexttoken())
			#list.append(str())
		#for i in list:
			#print i
		
if __name__=="__main__":
	p = scanner()
	print "Analisador lexico ver " + str(p.versao)
	nmfile = raw_input("Informe o nome do arquivo: [teste.pas]").strip()
	if nmfile == "":
		nmfile="teste.pas"
	p.setfile(nmfile)
	print p.getnexttoken(readonly=True)
	p.testeallfile()
